09. Interact with a Single Element
Interact with a Single Element
Question:
Start Quiz:
<!DOCTYPE html>
<!--
Unfortunately, this quiz will not be graded. If you do it correctly, the slider should respond to
touch and mouse events smoothly.
-->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Quiz - Touch Slider</title>
<link rel="stylesheet" href="css/styles.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
</head>
<body>
<div class="main">
<h3>Slide me</h3>
<div class="slider-main">
<svg id="line" height="48" width="300">
<line x1="0" y1="24" x2="300" y2="24" style="stroke:rgb(0,0,0);stroke-width:2" />
</svg>
<div id="toggle"><div class="markings">|||</div></div>
</div>
</div>
<script src="js/app.js"></script>
<script>
/*
No need to touch! Just blocks accidental scrolling
*/
// http://stackoverflow.com/questions/16348031/disable-scrolling-when-touch-moving-certain-element
window.blockMenuHeaderScroll = false;
$(window).on('touchstart', function(e) {
if ($(e.target).closest('.main').length == 1) {
blockMenuHeaderScroll = true;
}
});
$(window).on('touchend', function() {
blockMenuHeaderScroll = false;
});
$(window).on('touchmove', function(e) {
if (blockMenuHeaderScroll) {
e.preventDefault();
}
});
</script>
</body>
</html>
(function() {
/*
Write your code in the attachEventListeners() function defintion, which starts on line 88.
*/
/*
The actual grey box your finger touches.
*/
var toggle = document.querySelector('#toggle');
/*
The line that the toggle slides over.
*/
var line = document.querySelector('#line');
/**
* Keeps track of touches and determines where the toggle should be on the slider.
* @param {DOM node} toggle - The actual toggle that will be moving.
* @param {DOM node} line - The actual line that the toggle slides over.
*/
function ToggleTracker (toggle, line) {
var toggleRect = toggle.getBoundingClientRect();
var lineRect = line.getBoundingClientRect();
this._max = lineRect.width - toggleRect.width;
this._half = this._max / 2;
this._touchOffset = 0;
}
ToggleTracker.prototype = {
_touches: [],
/**
* Call this to register a movement.
* @param {Number} posX - The current x-position of the finger/mouse.
*/
addMovement: function (posX) {
this._touches[0] = this._touches[1] || posX;
this._touches[1] = posX;
},
/*
Call this to get the toggle's distance from the origin for
the CSS property: transform: translateX()
*/
getTranslateX: function () {
/*
How far the finger actually moved
*/
var dx = this._touches[1] - this._touches[0];
/*
transform: translateX() works by translating from a starting point. The idea is to
sum every dx to find the current distance from the origin.
*/
this._touchOffset = this._touchOffset + dx;
/*
I don't want to overwrite _touchOffset as it needs to stay constant between touches.
*/
var reportedValue = this._touchOffset;
/*
Make sure the toggle doesn't slide off the slider!
*/
if (reportedValue < 0) {
reportedValue = 0;
} else if (reportedValue > this._max) {
reportedValue = this._max;
}
return reportedValue;
}
};
/*
You could create multiple ToggleTrackers for multiple toggles.
*/
var toggleTracker = new ToggleTracker(toggle, line);
/*
Meant to be called by requestAnimationFrame for silky smooth 60fps performance.
#perfmatters - https://www.udacity.com/course/browser-rendering-optimization--ud860
*/
function slide() {
var translateX = toggleTracker.getTranslateX();
toggle.style.webkitTransform = "translateX(" + translateX + "px)";
toggle.style.transform = "translateX(" + translateX + "px)";
}
function attachEventListeners() {
/*
The idea is:
1) On start, set flag that toggle has started sliding (sliding = true). Attach the event to the toggle itself and add the first movement.
2) On move, if sliding has been activated, then register a new movement and animate the move.
Movement doesn't need to be limited to the toggle as it's easy for a finger/mouse to slip off.
3) On end, set flag that the toggle has stopped sliding. Once again, it doesn't need to be limited to the toggle as the finger/mouse can come up anywhere in the window.
*/
/*
Your code goes here!
*/
}
var sliding = false;
attachEventListeners();
})();
Solution:
INSTRUCTOR NOTE:
Event Listeners on MDN
Touch Events on MDN
Follow us online!
@cwpittman
@greenido
+greenido
Unfortunately, this quiz is not graded because it's tricky to reliably simulate touch and mouse events. You'll know you've completed this quiz when the toggle sticks to your finger/mouse and slides nicely.
You can either work in the classroom here or you can find a copy of the code to download and run in the Downloadables section.